--[[----------------------------------------------------------------------------
Adobe Photoshop Lightroom export plugin for Yandex.Fotki service
Version 1.0 RC2
http://aldeg.com/lightroom-plugins/
--------------------------------------------------------------------------------
$Id: YaFotkiExportProcess.lua 5 2009-04-26 18:23:43Z adegtiar $
--------------------------------------------------------------------------------
Copyright (c) 2009 Alexander A. Degtiar <adegtiar@gmail.com>

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

--------------------------------------------------------------------------------
Based on completely reworked YaFotki 0.2.3 plugin by Alexander Artemenko
Many thanks for his work
http://svetlyak.ru/blog/lightroom-plugins/
------------------------------------------------------------------------------]]


local LrMD5 = import 'LrMD5'


YaFotkiExportProcess = {}

function YaFotkiExportProcess.process ( functionContext, exportContext )

	--LrDialogs.message('Process')

    debug('YaFotkiExportProcess.process')
    local session = exportContext.exportSession
    local nPhotos = session:countRenditions()
    local p = exportContext.propertyTable

    local progress = exportContext:configureProgress {
        title = nPhotos > 1
            and LOC('$$$/Yandex/Upload/Progress=Uploading ^1 photos to Yandex.Fotki', nPhotos)
            or  LOC('$$$/Yandex/Upload/Progress/One=Uploading one photo to Yandex.Fotki')
        }

    for i, rendition in exportContext:renditions{stopIfCanceled = true} do
        local photo = rendition.photo
        local success, pathOrMessage = rendition:waitForRender()

        if progress:isCanceled() then break end

        if success then
            YaFotkiExportProcess.upload(exportContext, pathOrMessage, photo)
        else
            error(pathOrMessage)
        end

        LrFileUtils.delete(pathOrMessage)
    end
end



function YaFotkiExportProcess.upload(exportContext, path, photo)
    LrFunctionContext.callWithContext('YandexUpload', 
    function(context)
        LrDialogs.attachErrorDialogToFunctionContext(context)

        local fileName = LrPathUtils.leafName(path)
        local p = exportContext.propertyTable
        debug('Uploading ' .. path .. ' to the fotki.yandex.ru')

        local title, description, tags

        photo.catalog:withReadAccessDo( function()
            title = photo:getFormattedMetadata('title')
            if not title or #title == 0 then
                title = fileName
            end
            description = photo:getFormattedMetadata('caption')
            tags = photo:getFormattedMetadata('keywordTags')
        end )

        local url = 'http://up.fotki.yandex.ru/upload'

        local source = io.open(path, 'rb')
        local md5 = LrMD5.digest(source:read('*a'))
        local file_size = source:seek()

        local xml_path = LrFileUtils.chooseUniqueFileName( LrPathUtils.child(tmp_path, 'data.xml') )
        local frag_path = LrFileUtils.chooseUniqueFileName( LrPathUtils.child(tmp_path, 'frag.bin') )

        context:addCleanupHandler( function()
            -- cleanup
            LrFileUtils.delete(xml_path)
            LrFileUtils.delete(frag_path)
        end )
        
        
        
        local piece_size = 64000

        local client_xml = '<?xml version="1.0" encoding="utf-8"?>' ..
            '<client-upload md5="' .. md5 .. '" cookie="' .. md5 .. string.format('%s', os.time()) .. '">' ..
            '<filename>' .. fileName .. '</filename>' ..
            '<title>' .. title .. '</title>' ..
            '<description>' .. description .. '</description>' ..
            '<albumId>' .. tostring(p.selectedAlbum) .. '</albumId>' ..
            '<copyright>0</copyright>' ..
            '<xxx>' .. tostring(p.ya_mxxx) .. '</xxx>' ..
            '<tags>' .. tags .. '</tags>' ..
--            '<post2yaru>' .. tostring(p.ya_post2yaru) .. '</post2yaru>' ..
            '<disable_comments>' .. tostring(p.ya_disable_comments) .. '</disable_comments>' ..
            '<hide_orig>' .. tostring(p.ya_mhide_orig) .. '</hide_orig>' ..
            '<no_more_participation>' .. tostring(p.ya_no_more_participation) .. '</no_more_participation>' ..
            '<access>' .. tostring(p.ya_access) .. '</access>' ..
            '</client-upload>'

            debug('client-xml: ' .. client_xml)

            local xml = io.open(xml_path, 'wt')
            xml:write(client_xml)
            xml:close()

            -- PHOTO-START
            local mimeChunks = {
                { name = 'query-type', value = 'photo-start' },
                { name = 'piece-size', value = tostring(piece_size) },
                { name = 'file-size', value = tostring(file_size) },
                { name = 'checksum', value = md5 },
                { name = 'client-xml', fileName = 'data.xml', filePath = xml_path, contentType = 'text/xml' },
            }
            debug( 'photo-start: ' .. table2string(mimeChunks) )

            local result, headers = LrHttp.postMultipart(url, mimeChunks)
            if headers and headers.status ~= 200 then
                err( 'Error during upload, HTTP response: ' .. tostring(headers.status) )
            end
            debug('photo-start: ' .. result)
            cookie = result:match('cookie = "(%x+)"')
            debug('photo-start: cookie=' .. tostring(cookie))
            if cookie == nil then
                LrDialogs.message('error', '���������� ��������� ����������, ����������, ���������, ��� ����������� ��������� ������ ������� �, ���� ��� ���, �� ��������� � ������������� �� email ' .. PluginContactEmail .. '.', 'error')
                return
            end

            if isDebug then
                debug('Writing result on the disk')
                local f = io.open(LrPathUtils.child(tmp_path, 'upload-start.html'), 'wt')
                f:write(result)
                f:close()
            end

            -- PHOTO-PIECES
            mimeChunks = {
                { name = 'query-type', value = 'photo-piece' },
                { name = 'offset', value = '0' },
                { name = 'cookie', value = cookie },
                { name = 'fragment', fileName = 'frag.bin', filePath = frag_path },
            }
            current_offset = 0
            source:seek('set')
            local piece_num = 1
            while current_offset < file_size do
                mimeChunks[2].value = tostring(current_offset)
                local data = source:read(piece_size)
                if data == nil then
                    break
                end

                local frag = io.open(frag_path, 'wb')
                frag:write(data)
                frag:close()

                debug( 'photo-piece: ' .. table2string(mimeChunks) )
                local result, headers = LrHttp.postMultipart(url, mimeChunks)
                if headers and headers.status ~= 200 then
                    err( 'Error during upload, HTTP response: ' .. tostring(headers.status) )
                end
                debug('photo-piece: ' .. result)

                if isDebug then
                    debug('Writing result on the disk')
                    local f = io.open(LrPathUtils.child(tmp_path, 'upload-piece-' .. tostring(piece_num + 1) .. '.html'), 'wt')
                    f:write(result)
                    f:close()
                end
                current_offset = current_offset + #data
                debug('new offset is: ' .. tostring(current_offset))
                piece_num = piece_num + 1
            end

            -- PHOTO-CHECKSUM
            mimeChunks = {
                { name = 'query-type', value = 'photo-checksum' },
                { name = 'cookie', value = cookie },
                { name = 'size', value = tostring(piece_size) },
            }
            debug( 'photo-checksum: ' .. table2string(mimeChunks) )
            local result, headers = LrHttp.postMultipart(url, mimeChunks)
            if headers and headers.status ~= 200 then
                err( 'Error during upload, HTTP response: ' .. tostring(headers.status) )
            end
            debug('photo-checksum: ' .. result)

            if isDebug then
                debug('Writing result on the disk')
                local f = io.open(LrPathUtils.child(tmp_path, 'upload-checksum.html'), 'wt')
                f:write(result)
                f:close()
            end

            -- PHOTO-FINISH
            mimeChunks = {
                { name = 'query-type', value = 'photo-finish' },
                { name = 'cookie', value = cookie },
            }
            debug( 'photo-finish: ' .. table2string(mimeChunks) )
            local result, headers = LrHttp.postMultipart(url, mimeChunks)
            if headers and headers.status ~= 200 then
                err( 'Error during upload, HTTP response: ' .. tostring(headers.status) )
            end
            debug('photo-finish: ' .. result)

            if isDebug then
                debug('Writing result on the disk')
                local f = io.open(LrPathUtils.child(tmp_path, 'upload-finish.html'), 'wt')
                f:write(result)
                f:close()
            end
    end)
end
